Skip to content

Commit the acceptance instrument bytes, close schema holes, record known -00 defects - #2

Merged
laxsharma merged 3 commits into
mainfrom
fix/audit-corrections
Aug 7, 2026
Merged

Commit the acceptance instrument bytes, close schema holes, record known -00 defects#2
laxsharma merged 3 commits into
mainfrom
fix/audit-corrections

Conversation

@laxsharma

Copy link
Copy Markdown
Member

What this changes

Corrective fixes only. Nothing here adds the -01 design; it removes ways
the repository is currently misleading or lets invalid contracts pass.

  1. examples/acceptance-tests.txt is replaced by
    examples/acceptance-harness/, a real executable acceptance
    instrument. criteria_hash is now SHA-256 over the JCS-canonicalized
    manifest of that directory (relative path to SHA-256 of bytes), and
    taskspec.acceptance.harness_hash commits the same digest from
    inside the TaskSpec.
  2. Schema holes closed: empty acceptance objects, zero-length
    challenge windows, two-decimal-only money, kid outside the JOSE
    protected header, hard-coded tier enums, and the 100 percent
    min_bond_pct ceiling.
  3. tools/validate.py gains the rules JSON Schema cannot express,
    nine negative vectors, and an honest caveat about its restricted
    RFC 8785 implementation.
  4. README records the -00's known settlement defects and corrects three
    claims.

All commitments recomputed: spec_hash, criteria_hash,
harness_hash, vtc_hash.

Why

External review on x402-foundation/x402#3065 and two adversarial audit
rounds, all logged with dispositions in #1.

The headline item: criteria_hash committed an 85-byte file whose
entire content was a sentence describing the tests, so the commitment
covered a description of the acceptance criteria rather than the
criteria themselves. A party hosting the real harness could swap its
bytes after signature and submit the failure as a textbook-valid T0
fraud proof, slashing an honest counterparty's bond and keeping the
work. The reference implementation was teaching the vulnerability.

The schema items are the same class of problem: an empty acceptance
object made every fraud proof impossible while leaving optimistic
release unconditional, and a zero-length challenge window made release
instantaneous with no opportunity for a fraud proof to exist. Both
validated cleanly before this change.

Section(s) affected

No draft text changes in this PR. The repository is being corrected
ahead of -01 where a fix does not depend on unsettled design decisions.
Corresponding draft sections, for -01: 5.1 and 5.2 (hash coverage), 7
(tier registry), 4.3 (challenge window), 8 (x402 profile framing).

Deliberately not in this PR, because they depend on -01 design
decisions still open in #1: the Delivery object, the Verifier role,
attestation parties and facilitator countersignature, bond
sub-accounts, release and assurance members, and the liability.parent
object. Known gaps are marked with $comment pointers to #1 rather than
silently left.


  • python3 tools/validate.py passes (required if you touched
    examples/ or schemas/)
  • xml2rfc --text draft/draft-laxsharma-pact-00.xml builds, if you
    touched the draft — not applicable, the draft is unchanged

By submitting text you intend for the Internet-Draft, you accept the
IETF Note Well (https://www.ietf.org/note-well/), including the IPR
disclosure obligations of BCP 78 and BCP 79. See CONTRIBUTING.md.

Per CONTRIBUTING.md, substantive protocol changes belong in an issue
first. The design changes these corrections anticipate are logged in #1
with dispositions; this PR carries only the corrective subset that does
not presuppose how those are resolved.

Refs #1

laxsharma and others added 3 commits August 6, 2026 14:29
criteria_hash committed examples/acceptance-tests.txt, an 85-byte file
whose entire content was a sentence describing the tests. The commitment
therefore covered a description of the acceptance criteria rather than
the criteria themselves, so a party hosting the real harness could swap
its bytes after signature and manufacture a valid fraud proof against an
honest counterparty.

examples/acceptance-harness/ is now a real executable instrument, and
criteria_hash is SHA-256 over the JCS-canonicalized manifest of that
directory, mapping each file's relative path to the SHA-256 of its
bytes. A manifest of per-file digests rather than an archive digest
keeps the commitment reproducible without depending on tar or zip
metadata, which is not stable across producers.

Also closes the schema holes that let invalid contracts validate:

- acceptance had no required members, so an empty acceptance object
  validated, which made every fraud proof impossible while leaving
  optimistic release unconditional. Thresholds and an instrument are now
  both required, and an instrument URI must carry the hash of its bytes.
- challenge.window_seconds had a minimum of 0, so a zero-length window
  made optimistic release instantaneous with no opportunity for a fraud
  proof to exist. Raised to 1.
- money allowed exactly two decimals, which cannot express a bounty on a
  sub-dollar bond and made the micro-contract case that contract
  channels exist to serve arithmetically inexpressible.
- kid was a sibling of protected, placing the key identifier outside the
  signed data where it could be rewritten in transit. It now lives in
  the protected header, alongside alg and typ.
- the tier enum was hard-coded in three schemas while Section 14
  establishes an extensible registry, so a registered extension would
  have failed validation. It is now a pattern-constrained string.
- min_bond_pct was capped at 100 percent, which forbids the bond sizes
  that expected harm and the assurance constraint routinely require.

tools/validate.py gains the checks JSON Schema cannot express (parties
distinct, one signature per named party, protected headers carrying
alg, kid and typ with an allowed algorithm), nine negative vectors that
must be rejected, and an explicit caveat that its jcs() is a restricted
RFC 8785 implementation which does not evidence canonicalization
interoperability.

Recomputed commitments: spec_hash, criteria_hash, harness_hash, vtc_hash.

Refs #1 (entries 6 and 7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One external review and two adversarial audit rounds found that the
-00's settlement economics do not close. The full log with dispositions
is in #1. The README now carries the three findings a reader most needs
before implementing anything, and links the changelog issue directly
rather than the issue list.

Three claims corrected:

- the Complete bullet presented optimistic settlement as the design
  rather than as the -00 default that -01 changes
- criteria_hash is described as the instrument-manifest digest
- x402 composition is described as a release-policy profile over the
  merged auth-capture scheme. The -00 text calls pact-escrow a payment
  scheme, which is inaccurate: what PACT contributes is a release policy
  over an existing scheme, as x402-foundation/x402#3066 correctly names
  it.

Also records two honest caveats about what a green validator run does
and does not prove.

Refs #1

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The published .gitignore blocks PRIVATE-* and *.private.md but not
CLAUDE.md, CLAUDE.local.md or .claude/. Those hold local working context
that is not intended for this repository, and the working copy this
mirror is maintained from already excludes them. Bringing the published
list into line closes the gap rather than relying on those files simply
never being copied in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@laxsharma laxsharma closed this Aug 7, 2026
@laxsharma laxsharma reopened this Aug 7, 2026
@laxsharma
laxsharma merged commit 16b3efc into main Aug 7, 2026
2 checks passed
@laxsharma
laxsharma deleted the fix/audit-corrections branch August 7, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant